昨天我把一張自己開給自己的票:拖拉ticket解決了!
接著換下一張票、同時也就是今天的鐵人賽主題:改寫成Vuex來管理狀態~

在鐵人賽第13天的時候曾經聊到Vuex狀態管理,當我們的專案發展規模越來越大,元件越來越多,如何讓資料在跨元件之間溝通就是一件非常重要的事情。
(如果一直讓子元件用$emit傳給父元件、父元件再用props傳給其他子元件,這樣來來回回也太辛苦了吧~~~)
這時候,我們會使用Veux去產生一個用來管理網站全域的Shared State(共享狀態)的實體,而這個實體我們通常會把它取名叫做store(英文意思為倉庫)。
參考官網影片介紹的Vuex架構,今天我們就來把原本元件裡的data(如下圖左側)拉出來到store(下圖右側)獨立管理吧!

Vuex首先在Rails 6專案裡利用指令yarn add vuex安裝,這在第13天已經進行過了~
yarn add vuex
//略
...
success Saved lockfile.
success Saved 1 new dependency.
info Direct dependencies
└─ vuex@3.5.1
info All dependencies
└─ vuex@3.5.1
✨ Done in 3.30s.
在今天的任務,要從Vue元件裡的data拉出來、挪到store獨立管理的State叫做columns,先跟之前的元件寫法一樣,預設是一個空陣列。
如果元件想要使用State的話,是使用Getters屬性取值(state為Getter的第一個參數)
參考官網教學影片的Store流程圖:

我們寫在stores/column.js的路徑下的Vuex元件長得像這樣:
import Vue from 'vue/dist/vue.esm'
import Vuex from 'vuex'
Vue.use(Vuex)
// 定義一個新的 Vue Store
export default new Vuex.Store({
state: {
// 預設空陣列
columns: []
},
getters:{
columns: state => state.columns
},
mutations: {
// 任何更改columns的值的行為都必須透過mutation
UPDATE_COLUMNS(state, columns){
state.columns = columns;
}
},
actons: {
}
});
Vuex的store剛剛寫完熱騰騰的column.js趕快引入到原本的component:
import store from 'stores/column'
並且在new Vue裡面應該再加上store(import後就可以使用)
import Vue from "vue/dist/vue.esm";
import Column from "components/kanban/column"
import Rails from '@rails/ujs'
import Draggable from 'vuedraggable';
import store from 'stores/column';
document.addEventListener("turbolinks:load", () => {
let el = document.querySelector("#column");
if (el){
new Vue({
el,
store, // import後就可以使用store
data: {
kanban_id: el.dataset.kanbanid,
// columns: [] => 此時已經把column資料挪到Vuex裡了,原本的Vue可以把此段移除
},
components: { Column, Draggable },
methods: {
// 略
},
beforeMount(){
// 略
}
});
}
})
而Veux最大的重點是:之後有任何想要進行修改State的動作,都必須要透過Actions提交commit給Mutations。
(至於Actions在今天的需求裡該怎麼撰寫呢?稍安勿躁,請繼續往下看~)
之前在講解column元件時,有帶到生命週期的beforeMount(),在這個lifecycle hook會在畫面渲染至瀏覽器前的階段,把打API的結果更新至column陣列。
所以你應該猜到了~我們接下來要把以下這段beforeMount改寫進Actions:
beforeMount(){
Rails.ajax({
url: `/kanbans/${this.kanban_id}/columns.json`,
type: 'GET',
dataType: 'json',
success: result => {
this.columns = result;
},
error: error => {
console.log(error);
}
});
}
以下是Vuex作用的流程圖,為了透過Actions提交commit給Mutations,

我們把上一段搬移進去Vuex.Store的columns.js:
首先寫一個名為fetchColumn()的function,參數有commit,以及打後端API路徑需要知道的kanbanid
actions: {
fetchColumn({ commit }, kanbanid){
Rails.ajax({
url: `/kanbans/${kanban_id}/columns.json`,
///API路徑:kanbans/2/columns.json
type: 'GET',
dataType: 'json',
success: result => {
commit("UPDATE_COLUMNS", result);
//console.log(result);
},
error: error => {
// console.log(error);
}
});
}
}
以下是專案的程式碼截圖:
左邊代表原本的Vue寫法,右邊是改寫為Vuex
主要把beforeMounted的code移動到actions來,再透過commit給mutation把資料寫回去:

是不是跟Vuex官網的架構有87%像啊?(所以說~~官網要認真看!)

改寫完Vuex之後,點擊Kanban,可以順利載入Column以及所屬的ticket。
於是我們又可以把這一張票:改寫成vuex管理狀態移到DONE了 :)

小提醒:
javascript可以善用console log把接到的資料先印出來看看,加快開發速率!Vue devtool也要隨時開著,看有沒有紅字錯誤或警告訊息唷~:DRef: